﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace pipeCore.Pipes.Units.NamedPortUnits.Units
{
    /// <summary>
    ///  this will implement the unit that will reprint a unit that receive a downstream but do not send
    /// </summary>
    public interface ISinkunit : INamedpipeunit
    {
        /// <summary>
        /// Start the unit ports lining cycle
        /// </summary>
        void Run();
        /// <summary>
        /// This function will handle the event OnMessageRecivedFunction that is triggered by each port , before starting the ports the port must register its
        /// event handler to foreword to this function
        /// </summary>
        /// <param name="sender">the port that received the Message</param>
        /// <param name="e">the Message RecivedObject</param>
        void OnMessageRecived(Object sender, pipeCore.Pipes.Ports.OnMessageRecivedEventArg e);
        /// <summary>
        /// the in port collection
        /// </summary>
        Dictionary<String, pipeCore.Pipes.Ports.Iinport> PortsIn { set; get; }
    }

    /// <summary>
    /// represent a unit that receive request
    /// </summary>
    public abstract class Sink:ISinkunit
    {
        /// <summary>
        /// Run all the ports to listing for request
        /// </summary>
        public void Run()
        {
            try
            {
                string[] portname = PortsIn.Keys.ToArray();
                for (int i = 0; i < PortsIn.Keys.Count; i++) ((pipeCore.Pipes.Ports.Iinport)(PortsIn[portname[i]])).Listen();
            }
            catch (Exception err)
            {
                throw new Exception(err.Message);
            }
        }

        /// <summary>
        /// Called when the port receives a data
        /// </summary>
        /// <param name="sender">the object sender</param>
        /// <param name="e">the OnMessageRecivedEventArg</param>
        public abstract void OnMessageRecived(object sender, Ports.OnMessageRecivedEventArg e);
        /// <summary>
        /// Collection of inport
        /// </summary>
        public Dictionary<string, Ports.Iinport> PortsIn
        {
            get;
            set;
        }
        /// <summary>
        /// the unit name
        /// </summary>
        public string UnitName
        {
            get;
            set;
        }
        /// <summary>
        /// Add a new port to the unit
        /// </summary>
        /// <param name="port"></param>
        public void Add(Ports.IPort port)
        {
            if (port.GetType() == typeof(pipeCore.Pipes.Units.NamedPortUnits.ports.Inport))
            {
                PortsIn.Add("portin" + PortsIn.Count.ToString(),(pipeCore.Pipes.Ports.Iinport) port);
                port.Name = PortsIn.Count.ToString();
            }
            else
            {
                throw new Exception("this Unit just except Outputports");
            }
        }
        /// <summary>
        /// Add a new port to the collection
        /// </summary>
        /// <param name="port"></param>
        /// <param name="Name"></param>
        public void Add(Ports.IPort port, string Name)
        {
            try
            {
                PortsIn.Add(Name, (pipeCore.Pipes.Ports.Iinport)port);
                port.Name = Name;
                ((pipeCore.Pipes.Ports.Iinport)port).OnMessageRecive += new EventHandler<Ports.OnMessageRecivedEventArg>(OnMessageRecived);
            }
            catch (Exception err)
            {
                throw new Exception(err.Message);
            }
        
        }
        /// <summary>
        /// Add a new port to the unit
        /// </summary>
        /// <param name="portName">portname</param>
        public void Add(string portName)
        {
            pipeCore.Pipes.Units.NamedPortUnits.ports.Inport port = new pipeCore.Pipes.Units.NamedPortUnits.ports.Inport(portName);
            Add(port, portName);
        }
        /// <summary>
        /// Constract a new Sink Unit
        /// </summary>
        /// <param name="UnitName">the unit name</param>
        public Sink(String UnitName)
        {
            this.UnitName = UnitName;
            PortsIn = new Dictionary<string, Ports.Iinport>();
        }
        /// <summary>
        /// Constract a new Sink Object
        /// </summary>
        public Sink()
        {
            PortsIn = new Dictionary<string, Ports.Iinport>();
        }
        ISite site;
        /// <summary>
        /// Inherited from IComponent
        /// </summary>
        public event EventHandler Disposed;
        /// <summary>
        /// Inherited from IComponent
        /// </summary>
        public System.ComponentModel.ISite Site
        {
            get
            {
                return site;
            }
            set
            {
                site=value;
            }
        }
        /// <summary>
        /// Inhireted from IComponet
        /// </summary>
        public void Dispose()
        {
            string[] portname = PortsIn.Keys.ToArray();
            for (int i = 0; i < PortsIn.Keys.Count; i++)
                ((pipeCore.Pipes.Ports.Iinport)(PortsIn[portname[i]])).Dispose();
        }

        /// <summary>
        /// Called first to create and intalize the new unit
        /// </summary>
        public virtual void Create()
        {
            PortsIn = new Dictionary<string, Ports.Iinport>();
        }


        
    }




}
